<template>
  <!-- hHh lpR fFf ----hHh lpR fFf-->
  <q-layout class="topo-editor" view="lHh Lpr lff" @mousedown.stop>
    <q-header @mousedown.stop>
      <HmiHeader/>
    </q-header>

    <q-drawer
      v-model="leftDrawer"
      show-if-above
      bordered
      side="left"
      :width="240"
      @mousedown.stop
    >
      <div class="header-container bg-primary">
        <div class="logo-layout">
          <img src="../assets/logo.gif" width="30" height="30"/>
        </div>
        <div class="title-layout text-white">
          物联网平台
        </div>
      </div>
      <HmiToolbox/>
    </q-drawer>

    <q-page-container>
      <router-view />
    </q-page-container>
  </q-layout>
</template>

<script lang="ts">
import { defineComponent, onMounted, onUnmounted, ref } from 'vue';
import { storeToRefs } from 'pinia';
import { useCommonStore } from 'stores/commonStore';
import { EnumWSCommand, useScadaPacket } from 'src/hook/editor/useScadaPacket';
import { EnumWebsocketState, socket } from 'src/socket/websocket';
import { useMessageNotify } from 'src/hook/common/useMessageNotify';
import { cinBaseUrlAPI } from 'src/util/CinBaseConst';
import { GraphAppsItem } from 'pages/monitor/graph/GraphModel';
import { scaCatalogType } from 'src/util/ScaBaseConst';
import { useScaCatalogTbl } from 'src/hook/useScaCatalogTbl';
import { useCatalogTool } from 'src/hook/common/useCatalogTool';
import { ECommonConst } from 'src/util/BaseConst';
import { useEditorStore } from 'stores/editorStore';
import api from 'axios';

import Timeout = NodeJS.Timeout;
import HmiHeader from 'layouts/HmiHeader.vue';
import HmiToolbox from './HmiToolbox.vue';



export default defineComponent({
  name: 'MainLayout',
  components: {
    HmiHeader,
    HmiToolbox
  },

  setup () {
    //***************************************************************
    //      store
    //***************************************************************
    const store = useEditorStore();
    const commonStore = useCommonStore();
    let {
      leftDrawer,
      wsConnected,
      confirmed,
      application,
      user,
      varTbl
    } = storeToRefs(commonStore);

    //*********************************************************
    // 消息通知
    //*********************************************************
    //消息通知
    const {
      showMessage
    } = useMessageNotify();

    //*********************************************************************************************
    //      读取目录
    //*********************************************************************************************
    const {
      findCatalogLabel
    } = useCatalogTool();

    const {
      scaProjectList,
      getScaCatalog,
      removeScaCatalog
    } = useScaCatalogTbl();

    //*********************************************************************************************
    //      读取应用配置信息
    //*********************************************************************************************
    //当前项目ID
    let myProject = ref({
      id: 0,
      name: ''
    });

    //分页变量
    let pagination = ref({
      pageNum: 1,
      pageSize: ECommonConst.CARD_PAGE_SIZE,
      total: 20
    });

    //读取应用配置信息
    const getApplicationList = () => {
      api.post(cinBaseUrlAPI.CIN_APPLICATION_API_LIST, {
        pageNum: pagination.value.pageNum,
        pageSize: pagination.value.pageSize
      }).then((res) => {
        if (res.data.message === 'Success') {
          let list: GraphAppsItem[] = res.data.data;
          pagination.value.total = res.data.data.total;
          if (list.length > 0) {
            myProject.value.id = list[0].projectId;
            myProject.value.name = findCatalogLabel(scaProjectList.value, myProject.value.id);
            store.setProject(myProject.value.id, myProject.value.name);

            //连接websocket
            connectWebsocketServer();
          }
        } else {
          showMessage(res.data.message);
        }
      }).catch((error) => {
        showMessage(error.message);
      })
    }

    //*********************************************************
    // websocket
    //*********************************************************
    let wsTimer: Timeout;

    //socket通信函数
    const {
      WS_FRAME_HEADER,
      wsCertifyUser,
      wsRegisterVariable,
      wsReadVariable
    } = useScadaPacket();

    //web socket连接成功
    const onWebsocketConnected = () => {
      //连接状态
      commonStore.setWebscoketConnection(1);

      //提示
      showMessage('Websocket服务器连接成功！');

      //认证
      wsCertifyUser(socket, user.value.username,
        user.value.password, application.value.projectId);
    }

    //web socket接收函数，msg为ArrayBuffer
    const onWebsocketReceived = (msg: any) => {
      //连接状态
      commonStore.setWebscoketConnection(1);

      //二进制ArrayBuffer类型接收数据
      let len = msg.byteLength;
      let uint8Arr = new Uint8Array(msg);

      //解析
      let vid = 0, vdata = 0, status = 0;
      let ofs = 0;
      let header = (uint8Arr[ofs++] << 8) | uint8Arr[ofs++];
      let command = (uint8Arr[ofs++] << 8) | uint8Arr[ofs++];
      let size = (uint8Arr[ofs++] << 8) | uint8Arr[ofs++];

      //帧格式判断
      if ((header !== WS_FRAME_HEADER) || (len !== size + 6)) {
        console.log('数据帧格式不正确！');
        return;
      }

      //帧解析
      switch (command) {
        case EnumWSCommand.WS_CERTIFY_USER:
          if (size === 2) {
            status = (uint8Arr[ofs++] << 8) | uint8Arr[ofs++];
            if (status === 1) {
              wsRegisterVariable(socket, varTbl.value);
            }
          }
          break;
        case EnumWSCommand.WS_REGISTER_VARIABLE:
          if (size === 2) {
            status = (uint8Arr[ofs++] << 8) | uint8Arr[ofs++];
            if (status === 1) {
              wsReadVariable(socket, varTbl.value);
            }
          }
          break;
        case EnumWSCommand.WS_READ_VARIABLE:
          if (size % 6 === 0) {
            let num = size / 6;
            for (let i = 0; i < num; i++) {
              vid = (uint8Arr[ofs++] << 24) | (uint8Arr[ofs++] << 16) | (uint8Arr[ofs++] << 8) | uint8Arr[ofs++];
              vdata = (uint8Arr[ofs++] << 8) | uint8Arr[ofs++];
              commonStore.addVariableTbl(vid, vdata);
            }
          }
          break;
        case EnumWSCommand.WS_READ_DEV_CONNECTION:
          if (size % 6 === 0) {
            let num = size / 6;
            for (let i = 0; i < num; i++) {
              //deviceId
              vid = (uint8Arr[ofs++] << 24) | (uint8Arr[ofs++] << 16) | (uint8Arr[ofs++] << 8) | uint8Arr[ofs++];
              //status
              vdata = (uint8Arr[ofs++] << 8) | uint8Arr[ofs++];
              console.log('connection status:' + vdata.toString());
              commonStore.addDeviceTbl(vid, vdata);
            }
          }
          break;
        case EnumWSCommand.WS_GET_DEV_CONNECTION_INFO:
          if (size >= 6) {
            let conn = { total: 0, online: 0, offline: 0 };
            conn.total = (uint8Arr[ofs++] << 8) | uint8Arr[ofs++];
            conn.online = (uint8Arr[ofs++] << 8) | uint8Arr[ofs++];
            conn.offline = (uint8Arr[ofs++] << 8) | uint8Arr[ofs++];
            commonStore.setDevConnTbl(conn);
          }
          break;
        default:
          break;
      }
    }

    //开启websocket
    const connectWebsocketServer = () => {
      //开始连接
      //socket.connect('ws://192.168.1.76:6678');
    }

    //关闭
    const onWebsocketClosed = () => {
      commonStore.setWebscoketConnection(0);
    }

    //挂载
    onMounted(() => {
      console.log('MainLayout');

      //初始化
      socket.init(onWebsocketReceived, onWebsocketConnected, onWebsocketClosed);

      //cataItem
      getScaCatalog(scaCatalogType.PROJECT_CODE);

      //读取应用配置信息, myProject.value.id发生变化，自动生产项目树
      getApplicationList();

      //创建websocket连接检查定时器,60s
      wsTimer = setInterval(() => {
        let status = socket.getStatus();
        console.log('Websocket Status:' + status);
        if ((confirmed.value) &&
          ((!wsConnected.value) || (status === EnumWebsocketState.WS_CLOSED))) {
          connectWebsocketServer();
        }
      }, 60000);
    })

    //组件卸载
    onUnmounted(() => {
      //清除定时器
      clearInterval(wsTimer);

      //cataItem
      removeScaCatalog(scaCatalogType.PROJECT_CODE);
    })

    return {
      leftDrawer
    };
  }
});
</script>

<style lang="scss" scoped>
.header-container {
  display: flex;
  margin: 0px;
  padding: 0px;
  height: 50px;
  flex-direction: row;
  align-items: center;
  justify-content: flex-start;

  .logo-layout {
    height: 40px;
    width: 40px;
    margin-top: 5px;
    margin-left: 10px;
  }
  .title-layout {
    font-size: 18px;
    font-weight: normal;
  }
}

</style>

